import axios,{AxiosInstance,AxiosRequestConfig} from 'axios';
import {storageSet,storageGet,storageDel} from '../common';
import {PlainObject} from '../../../types';
import Modal from '../../components/app/modal';
import Toast,{ResultType} from '../../components/app/toast';

const {cmp}=window;
let isCmpReady=false;
let cmpTasks:Array<Function>=[];
/**
 * 在cmp.ready以后,执行cmp相关方法
 * 注意: callback方法也能返回Promise
 * @param callback 执行的方法(在cmp.ready以后调用)
 * @param result 没有cmp时的备用返回值
 * @param fnResult 没有cmp时的备用返回值(方法的返回值)
 * @return Promise,接收的值是传入的callback方法返回值
 */
function cmpWrap<T>(callback:(cmpw:any)=>T,result:T,fnResult?:()=>T):Promise<T>{
	if(cmp){
		if(isCmpReady){
			return Promise.resolve(callback(cmp));
		}else{
			return new Promise(function(resolve){
				cmpTasks.push(function(cmpw:any){
					resolve(callback(cmpw));
				});
			});
		}
	}else{
		console.log('不存在cmp!');
		if(fnResult){
			return Promise.resolve(fnResult());
		}else{
			return Promise.resolve(result);
		}
	}
}
if(cmp){
	cmp.ready(function(){
		isCmpReady=true;
		for(let i=0;i<cmpTasks.length;++i){
			cmpTasks[i](cmp);
		}
		cmpTasks=[];
	});
}
/**
 * 封装了m3和微协同的返回传值
 * @property listen 监听返回
 * @property data 传值
 * @property goBack 通过调用来返回
 */
interface IBackEvent{
	key:string,
	listen(data:PlainObject):void,
	goBack(backCount:number,backParam?:PlainObject):void,
}
let BackEventListener:(data:PlainObject) => void=function(){};
const BackEvent:IBackEvent={
	key:'lexmis_webview_back_data',
	goBack(backCount:number=1,backParam?:PlainObject):void{
		cmpWrap(function(cmpw){
			storageSet(BackEvent.key,backParam);
			//执行返回操作
			cmpw.href.back(backCount);
		},undefined);
	},
	get listen(){
		return BackEventListener;
	},
	//微协同父页面,如果缓存中有值,则执行监听方法
	set listen(val:(data:PlainObject) => void){
		BackEventListener=val;
		//region 微协同端监听子页面返回
		cmpWrap(function(cmpw){
			if(!cmpw.platform.CMPShell){
				const backFn=() => {
					const data=storageGet(BackEvent.key);
					storageDel(BackEvent.key);
					if(data){
						val(data);
					}
				};
				window.addEventListener('pageshow',() => {
					backFn();
				});
				backFn();
			}
		},undefined);
		//endregion
	},
};
cmpWrap(function(cmpw){
	cmpw.backbutton();
	//region m3端监听子页面返回
	if(cmpw.platform.CMPShell){
		//父页面, 监听到子页面的返回
		document.addEventListener('com.seeyon.m3.phone.webBaseVC.didAppear',function(e){
			//父页面执行监听方法
			const data=storageGet(BackEvent.key);
			storageDel(BackEvent.key);
			if(typeof BackEvent.listen==='function'&&data){
				BackEvent.listen(data);
			}
		});
	}
	//endregion
},undefined);
let loadCount=0;
let msg:string;
let loadInstance:ResultType|null;
interface LoadingOption{
	delay?:number;
}
/**
 * 加载提示框(打开关闭必须成对出现,保证在第一次打开时打开,最后一次关闭时关闭)
 * @param show 传false表示关闭,不传或者传字符串表示显示
 * @param option 选项
 */
function loading(show?:string|boolean,option:LoadingOption={}):void{
	const delay=option.delay||0;
	if(show!==false){
		const curMsg=show&&show!==true?show:'加载中...';
		// 只在第一次提示
		if(!loadCount++||msg!==curMsg){
			if(delay){
				window.setTimeout(() => {
					if(loadCount&&(loadInstance==null||msg!==curMsg)){
						msg=curMsg;
						loadInstance=Toast.loading(msg);
					}
				},delay);
			}else{
				msg=curMsg;
				loadInstance=Toast.loading(msg);
			}
		}
	}else{
		if(!(--loadCount)){
			if(loadInstance){
				loadInstance.close();
				loadInstance=null;
			}
		}else if(loadCount<0){
			loadCount=0;
		}
	}
}
//构建用于请求的axios
let {
	VUE_APP_PROXY_HOST,
	VUE_APP_PROXY_USERNAME,
	VUE_APP_PROXY_PASSWORK,
	VUE_APP_PROXY_LOGINNAME,
	VUE_APP_REQUEST_TIMEOUT,
	proxyHost,
	proxyUserName,
	proxyPassword,
	proxyLoginName,
	requestTimeout,
}=process.env;
proxyHost||=VUE_APP_PROXY_HOST;
proxyUserName||=VUE_APP_PROXY_USERNAME;
proxyPassword||=VUE_APP_PROXY_PASSWORK;
proxyLoginName||=VUE_APP_PROXY_LOGINNAME;
requestTimeout||=VUE_APP_REQUEST_TIMEOUT;
const requestTimeoutNum=parseInt(requestTimeout||'6000');
let myAxios:Promise<AxiosInstance>;
if(proxyHost){
	const tokenUrl=`${proxyHost}/seeyon/rest/token/${proxyUserName}/${proxyPassword}?loginName=${encodeURIComponent(proxyLoginName||'')}`;
	myAxios=axios.get<any>(tokenUrl,{
		timeout:requestTimeoutNum
	}).then(function(response){
		return axios.create({
			method:'post',
			baseURL:'/seeyon/rest/',
			headers:{
				token:response.data.id
			},
			timeout:requestTimeoutNum
		});
	});
}else{
	// @ts-ignore
	myAxios=cmpWrap(
		function(cmpw){
			return {
				request(config:AxiosRequestConfig){
					return new Promise(function(resolve,reject){
						const param={
							url:cmpw.seeyonbasepath+'/rest/'+(config.url||''),
							async:true,
							type:config.method||'post',
							dataType:'json',
							timeout:requestTimeoutNum,
							data:JSON.stringify(config.data),
							headers:{
								'Content-Type':'application/json; charset=utf-8',
								'Accept-Language':'zh-CN',
								token:cmpw.token,
								...config.headers,
							},
							success(result:any){
								resolve({
									// @ts-ignore
									data:result,
								});
							},
							error(error:any){
								cmpw.errorHandler(error);
								// eslint-disable-next-line prefer-promise-reject-errors
								reject({
									response:{
										data:error,
										status:error.code,
									},
								});
							},
						};
						cmpw.ajax(param);
					});
				}
			};
		},
		axios.create({
			method:'post',
			baseURL:'/seeyon/rest/',
			timeout:requestTimeoutNum
		})
	);
}
/**
 * 请求服务器
 * @param url 请求路径
 * @param data 请求参数
 * @param config 请求配置
 * @param noLoadingTip 是否不显示加载中
 * @param option 加载提示选项
 * @return Promise,接收的值是服务器返回的数据
 */
function service(url:string,data:PlainObject={},config?:AxiosRequestConfig,noLoadingTip?:boolean,option:{content?:string}&LoadingOption={}):Promise<any>{
	if(!noLoadingTip){
		loading(option.content||true,option);
	}
	if(config?.method==='get'){
		config.params=data;
	}else if(data.params==null){
		data.params={};
	}
	const req=myAxios.then(function(axios){
		return axios.request(
			Object.assign({
				url,
				data,
			},config)
		);
	});
	return req.then(function(response){
		return response.data;
	}).catch(function(e){
		const errInfo:PlainObject={
			url,
			data,
			config,
			noLoadingTip,
			realConfig:e.config,
		};
		let errInfoText='请求参数\n'+JSON.stringify(errInfo,null,'  ');
		if(e.response){
			errInfoText+='\n响应\n'+JSON.stringify(e.response,null,'  ');
			if(e.response.data.message){
				Modal.serviceError({
					content:e.response.data.message,
					info:errInfoText,
				});
			}else{
				Modal.serviceError({
					content:'服务器错误！'+e.response.status,
					info:errInfoText,
				});
			}
			errInfo.response=e.response;
			console.log('服务器错误！',errInfo);
		}else if(e.request){
			errInfoText+='\n请求\n'+JSON.stringify(e.request,null,'  ');
			Modal.serviceError({
				content:'请求已发送，未响应！',
				info:errInfoText,
			});
			errInfo.request=e.request;
			console.log('HTTP请求失败(未响应)',errInfo);
		}else{
			Modal.serviceError({
				content:'请求异常！',
				info:errInfoText,
			});
			console.log('HTTP请求失败(请求异常)',errInfo);
		}
		throw e;
	}).finally(function(){
		if(!noLoadingTip){
			loading(false);
		}
	});
}
/**
 * 根据图片文件id,获取图片的链接
 * @param fileIds 文件id的数组
 * @return Promise,接收的值是图片链接的数组
 */
function getImgsPromise(fileIds:Array<string>):Promise<string[]>{
	return cmpWrap(function(cmpw){
		return cmpw.seeyonbasepath;
	},location.origin).then(function(base){
		return fileIds.map(function(fileId){
			return base+'/fileUpload.do?method=showRTE&type=image&fileId='+fileId;
		});
	});
}
/**
 * 打开页面
 * @param url			页面的路径
 * @param data			传参
 * @param newWebView	是否新开WebView
 * @param isForm		是否是表单(解决微协同值丢失)
 * @param nativeBanner	是否启用原生导航条
 */
function page(url:string,data:PlainObject,newWebView=true,isForm=false,nativeBanner=false):void{
	cmpWrap(function(cmpw){
		if(isForm){
			const eventName=cmpw.platform.CMPShell?'beforeviewleave':'beforepageredirect';
			cmp.event.trigger(eventName,document,{
				scope:'root',
				location:'store',
				done(){
					cmpw.href.next(url,data,{
						openWebViewCatch:newWebView,
						nativeBanner,
					});
				}
			});
		}else{
			cmpw.href.next(url,data,{
				openWebViewCatch:newWebView,
				nativeBanner
			});
		}
	},undefined);
}
/**
 * 打开表单
 * @param templateId
 * @param param
 */
function sendCollaboration(templateId:String,param:PlainObject={}){
	cmpWrap((cmpw) => {
		let baseURL;
		if(cmpw.platform.CMPShell){
			baseURL='http://collaboration.v5.cmp/v1.0.0';
		}else{
			baseURL='/seeyon/m3/apps/v5/collaboration';
		}
		page(baseURL+'/html/newCollaboration.html',{
			...param,
			templateId:templateId,
			backIndex:1,
			preCaches:['m3_v5_collaboration_tpl_level_cache_key','m3_v5_collaboration_templateindex_cache_key'],
		});
	},undefined);
}
function openSummary(
	{
		openFrom='glwd',
		summaryId,
		baseObjectId,
	}:Record<string,any>
){
	cmpWrap((cmpw) => {
		let baseURL;
		if(cmpw.platform.CMPShell){
			baseURL='http://collaboration.v5.cmp/v1.0.0';
		}else{
			baseURL='/seeyon/m3/apps/v5/collaboration';
		}
		page(baseURL+'/html/details/summary.html',{
			openFrom,
			summaryId,
			baseObjectId,
		});
	},undefined);
}
export {
	//在cmp.ready以后,执行cmp相关方法
	cmpWrap,
	//封装了m3和微协同的返回传值
	BackEvent,
	//加载提示框(打开关闭必须成对出现,保证在第一次打开时打开,最后一次关闭时关闭)
	loading,
	//请求服务器
	service,
	//根据文件id获取图片的链接
	getImgsPromise,
	//打开页面
	page,
	//打开表单
	sendCollaboration,
	openSummary,
};